package main;

import java.awt.Point;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;

import events.CustomEvent;
import events.CustomListener;
import events.event.MapLoadedEvent;
import events.listener.CanvasListener;

import sprites.CharacteristicSprite;
import sprites.Coin;
import sprites.Sprite;
import sprites.characteristic.MonsterSpawn;
import sprites.characteristic.PlayerSpawn;

public class MapLoader implements CustomListener {
	private final String FOLDER = "src/map";
	private final Character COMMENT = '#';

	private File[] maps;
	private int currentMap = 0;
	private HashMap<Character, Sprite> spriteMap = new HashMap<Character, Sprite>();

	private HashMap<Point, Sprite> map;
	private ArrayList<PlayerSpawn> playerSpawn;
	private ArrayList<MonsterSpawn> monsterSpawn;

	private int height = 0;
	private int width = 0;

	public MapLoader() {
		EventManager.addListener(this);
		getMaps();
	}

	public void loadMap() {
		if (currentMap > getTotal())
			currentMap = 0;
		File current = maps[currentMap];
		ArrayList<String> lines = new ArrayList<String>();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(
					new FileInputStream(current)));
			String line;
			while ((line = br.readLine()) != null) {
				if (line.charAt(0) != COMMENT) {
					lines.add(line);
				}
			}
			currentMap++;
			parseMap(lines);
		} catch (IOException e) {
			System.err.println(e.getMessage());
		}
	}

	/**
	 * Parses map.
	 * 
	 * @param lines
	 */
	private void parseMap(ArrayList<String> lines) {
		height = lines.size();
		
		playerSpawn = new ArrayList<PlayerSpawn>();
		monsterSpawn = new ArrayList<MonsterSpawn>();
		
		map = new HashMap<Point, Sprite>();
		for (int y = 0; y < lines.size(); y++) {
			String s = lines.get(y);
			if (s.length() > width) {
				width = s.length();
			}
			for (int i = 0; i < s.length(); i++) {
				char tmp = s.charAt(i);
				Sprite cs;
				try {
					cs = spriteMap.get(tmp);
					if (cs != null) {
						cs = cs.getClass().newInstance();
						if (cs instanceof PlayerSpawn) {
							addPlayerSpawn((PlayerSpawn) cs);
						}
						if (cs instanceof MonsterSpawn) {
							addMonsterSpawn((MonsterSpawn) cs);
						}
					} else {
						cs = new Coin();
					}
					map.put(new Point(i, y), cs);
				} catch (InstantiationException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
		mapLoaded();
	}

	private void mapLoaded() {
		EventManager.fire(new MapLoadedEvent(map, width, height, monsterSpawn, playerSpawn),
				CanvasListener.class);
	}

	public void getMaps() {
		File folder = new File(FOLDER);
		maps = folder.listFiles();
	}

	public int getTotal() {
		return maps.length;
	}

	public void addSprite(CharacteristicSprite s) {
		char symb = s.getSymbol();
		if (spriteMap.containsKey(symb)) {
			System.err
					.println("Multiple characteristic sprites with the same key. Key: '"
							+ symb + "', Sprite: '" + s + "'");
			return;
		}
		spriteMap.put(symb, s);
	}

	@Override
	public void EventOccurred(CustomEvent evt) {
		// TODO Auto-generated method stub

	}

	public void addPlayerSpawn(PlayerSpawn cs) {
		playerSpawn.add(cs);
	}

	public void addMonsterSpawn(MonsterSpawn cs) {
		monsterSpawn.add(cs);
	}
}
